//process.cc

#include "process.h"
#include "system.h"

ProcessTableThread::ProcessTableThread(Thread *thread){
  mythread = thread;
  stackReg = -1;
 
}

ProcessTableThread::~ProcessTableThread(){
 
}
//get a pointer to the thread that this data structure represents
Thread* ProcessTableThread::getMyThread()
{
  return mythread;
}

int* ProcessTableThread::getbitMapLoc(){
  return bitMapLoc;
}

int* ProcessTableThread::getpageTblLoc(){
  return pageTblLoc;
}



void ProcessTableThread::setStackReg(int v) {
  stackReg = v;
}

int ProcessTableThread::getStackReg(){
  return stackReg;
}


int Process::idCount = 0;

//put somewhere else:
#define NEW_PROCESS_BITMAP_SIZE 50

Process::Process(AddrSpace * newspace){
	id = idCount++;
	threads = new List;
	myLocks = new List;
	myConditions = new List;
	space = newspace;
	processLock = new Lock("Process Lock");
	numActiveThreads = 0;
#ifdef NETWORK
	mailbox = -1;
#endif
}

Process::~Process(){
  delete threads;
  delete space;
  delete processLock;
  delete myLocks;
  delete myConditions;
	
}

int Process::getID(){
	return id;
}

AddrSpace* Process::getAddrSpace(){
  return space;
}

//frequently used method which is the main way that a fuction can gain access
//to the data of a thread
ProcessTableThread* Process::getThread(Thread *thread){
  
  processLock->Acquire();

  ProcessTableThread* targetThread = NULL;
  bool found = false;

  //Assuming order matters:
  //Create a temporary list to hold the threads list
  List * temp = new List;
  
  if(threads->IsEmpty())
    {
      printf("%s : Process::getThread() should not get thread from process that has no threads\n",currentThread->getName());
    }
  //While the thread list is not empty
  while(!threads->IsEmpty()){

    //Remove the top thread from the threads list
    ProcessTableThread* topthread = ( ProcessTableThread *)threads->Remove();
    if(topthread == NULL){
      printf("%s : Process::getThread() - Top thread is NULL!\n",currentThread->getName());
    }

	 
    //If top thread is equal to tread passed in, then return top thread.
      if(topthread->getMyThread() == thread){
	targetThread = topthread;
	found = true;
      }
      
   
      // else printf("Process::getThread(): THREAD NOT FOUND!!\n");
		 
		
    //append the top thread to the temporary list
    temp->Append((void *)topthread);
  }

  //After removing the desired thread and emptying the threads list
  //Set the threads list to the temp thread;
  threads = temp;

  if(!found)
    {
      printf("Process::getThread() called by thread %s looking for thread %s: THREAD NOT FOUND!!\n" , currentThread->getName(),thread->getName());
      printThreads();
    }


  processLock->Release();

  return targetThread;
 
}

void Process::addThread(Thread * newthread){

  // processLock->Acquire();
  //assemble the ProcessTable Thread then add it
  ProcessTableThread *ptt = new ProcessTableThread(newthread);

  //if mainthread then no parent to add it to
 
  threads->Append(ptt);
      
  numActiveThreads++;

  //processLock->Release();

}

void Process::removeThread(Thread * oldthread){

  processLock->Acquire();
 
  int numActive = 0;
  	//Assuming order matters:
	//Create a temporary list to hold the threads list
	List * temp = new List;
	
	//While the thread list is not empty
	while(!threads->IsEmpty()){

		//Remove the top thread from the threads list
		  ProcessTableThread* topthread = ( ProcessTableThread *)threads->Remove();

		  if(topthread->getMyThread() != oldthread)
		    {
		      //we found thread now dont put it back
		      //then return
		      	//Otherwise append the top thread to the temporary list
		      temp->Append((void *)topthread);
		    }
		  else
		    {
		      
		     
		      //printf("%s thread found and deleted\n",oldthread->getName());
		   //    int *bitMapLoc = topthread->getbitMapLoc();
		      
// 		      MMLock->Acquire();

// 		      for(int i = 0; i < 8; i++)
// 			{
// 			  mainMemory->Clear(bitMapLoc[i]);
// 			}

// 		      MMLock->Release();

		   
		      topthread->~ProcessTableThread();
		    }
	}

	//After removing the desired thread and emptying the threads list
	//Set the threads list to the temp thread;
	threads = temp;

	
	numActiveThreads--;
	processLock->Release();
  
}



int Process::getNumActiveThreads()
{

	return numActiveThreads;

	//processLock->Release();
  
}





void Process::Clear(int i) {

  //processLock->Acquire();

  space->Clear(i);

  //processLock->Release();
}  




 //methods to add and destroy locks
void Process::addLock(int i){
  myLocks->Append((void *)i);
}


//removes it form the process and also calls remove in the synchTable
void Process::removeLock(int i){
   
  processLock->Acquire();
 
 
  	//Assuming order matters:
	//Create a temporary list to hold the threads list
	List * temp = new List;
	
	//While the thread list is not empty
	while(!myLocks->IsEmpty()){

		//Remove the top thread from the threads list
		  int lock = (int)myLocks->Remove();

		  if(lock != i)
		    {
		      temp->Append((void *)lock);
		    }
		  else
		    {
		      printf("lock of number %d deleted\n",lock);
		    }
		  
	}

	//After removing the desired thread and emptying the threads list
	//Set the threads list to the temp thread;
	myLocks = temp;
	
	synchTable->removeLock(i);

	processLock->Release();
}
  
  //methods to add and destroy condition variables
void Process::addCondition(int i){
  myConditions->Append((void *)i);
}

//removes it form the process and also calls remove in the synchTable
void Process::removeCondition(int i){
   
  processLock->Acquire();
 
 
  	//Assuming order matters:
	//Create a temporary list to hold the threads list
	List * temp = new List;
	
	//While the thread list is not empty
	while(!myConditions->IsEmpty()){

		//Remove the top thread from the threads list
		  int lock = (int)myConditions->Remove();

		  if(lock != i)
		    {
		      temp->Append((void *)lock);
		    }
		  else
		    {
		      printf("lock of number %d deleted\n",lock);
		    }
		  
	}

	//After removing the desired thread and emptying the threads list
	//Set the threads list to the temp thread;
	myConditions = temp;
	
	synchTable->removeCondition(i);

	processLock->Release();
}



 //debug method to print out locks of process
void Process::printLocks(){
  
  processLock->Acquire();
  printf("locks of this process are ");
  	//Assuming order matters:
	//Create a temporary list to hold the threads list
	List * temp = new List;
	

	//While the thread list is not empty
	while(!myLocks->IsEmpty()){

		//Remove the top thread from the threads list
		  int lock = (int)myLocks->Remove();

		  printf("%d",lock);
		  printf(", ");
		  temp->Append((void *)lock);
	}

	//After removing the desired thread and emptying the threads list
	//Set the threads list to the temp thread;
	myLocks = temp;

	printf("\n");
	processLock->Release();
}
  
  //debug method to print out condition variables of process
void Process::printConditions(){
  
  processLock->Acquire();
  // printf("Conditions of %s are ",Name);
  	//Assuming order matters:
	//Create a temporary list to hold the threads list
	List * temp = new List;
	

	//While the thread list is not empty
	while(!myConditions->IsEmpty()){

		//Remove the top thread from the threads list
		  int condition = (int)myConditions->Remove();

		  printf("%d",condition);
		  printf(", ");
		  temp->Append((void *)condition);
	}

	//After removing the desired thread and emptying the threads list
	//Set the threads list to the temp thread;
	myConditions = temp;

	printf("\n");
	processLock->Release();
}

void Process::printThreads(){

  processLock->Acquire();
  printf("threads remaining are ");
  	//Assuming order matters:
	//Create a temporary list to hold the threads list
	List * temp = new List;
	

	//While the thread list is not empty
	while(!threads->IsEmpty()){

		//Remove the top thread from the threads list
		  ProcessTableThread* topthread = ( ProcessTableThread *)threads->Remove();

		  printf("%s",topthread->getMyThread()->getName());
		  printf(", ");
		  temp->Append((void *)topthread);
	}

	//After removing the desired thread and emptying the threads list
	//Set the threads list to the temp thread;
	threads = temp;
	printf(" and numActiveThreads is %d\n",numActiveThreads);

	processLock->Release();
}



#ifdef NETWORK
//Set the mail box number for this process
void Process::setMailBox(int num){
	mailbox = num;
}

//Get the mail box number for this proces
int Process::getMailBox(){
	return mailbox;
}

#endif

